﻿using System;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Web.Mvc;
using Hallenberg.SmartClient.Interfaces;
using Hallenberg.SmartClient.Menu;

namespace Hallenberg.SmartClient.MVC.TypeHandlers
{
    public class MenuItemAttributeHandlerMvc : IAttributeTypeHandlerExtender
    {
        private IMenuManager m_MenuManager;

        public MenuItemAttributeHandlerMvc(IMenuManager menuManagers)
        {
            Debug.Assert(menuManagers != null);

            if (menuManagers == null)
            {
                throw new ArgumentNullException("menuManagers");
            }

            m_MenuManager = menuManagers;
        }

        public Type HandledType
        {
            get { return typeof(MenuItemAttribute); }
        }

        public bool Handle(Type attachedToClass, MethodBase attachedToMethod, Attribute attributeInstance, Attribute[] allAttributes)
        {
            MenuItemAttribute typedAttribute = (MenuItemAttribute)attributeInstance;

            MenuItemContainer menuContainer = m_MenuManager.Find(typedAttribute.MenuCollectionName, true);

            Debug.Assert(menuContainer != null);

            if (menuContainer == null)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "menuContainer '{0}' could not be found", typedAttribute.MenuCollectionName));
            }

            MenuItem menuItem = menuContainer.FindMenuItem(typedAttribute.MenuItemName);

            Debug.Assert(menuItem != null);
            if (menuItem == null)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Menu item [{0}] does not exist in system.", typedAttribute.MenuItemName));
            }

            menuItem.AttachedToClass = MVC.NameResolver.GetControllerName(menuItem.AttachedToClass);

            ///////////////////////////////////////////////////////////////////
            // Ensuring that authorization attributes are examined and applies
            // the roles and users to the created menu item.
            ///////////////////////////////////////////////////////////////////

            foreach (AuthorizeAttribute authorizeAttribute in allAttributes.Where(attr => attr.GetType() == typeof(AuthorizeAttribute)))
            {
                if (string.IsNullOrEmpty(authorizeAttribute.Roles) == false)
                {
                    menuItem.AddRequiredRoles(authorizeAttribute.Roles.Split(','));
                }

                if (string.IsNullOrEmpty(authorizeAttribute.Users) == false)
                {
                    menuItem.AddRequiredUsers(authorizeAttribute.Users.Split(','));
                }
            }

            return true;
        }
    }
}
